package edu.pku.sei.transformation.atl.adapter;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import edu.pku.sei.transformation.atl.rule.IATLHeader;
import edu.pku.sei.transformation.atl.rule.IATLHelper;
import edu.pku.sei.transformation.atl.rule.IATLImport;
import edu.pku.sei.transformation.atl.rule.IATLMetaModel;
import edu.pku.sei.transformation.atl.rule.IATLModule;
import edu.pku.sei.transformation.atl.rule.IATLRule;
import edu.pku.sei.transformation.editor.model.AtomicTransformation;
import edu.pku.sei.transformation.editor.model.MetaModel;
import edu.pku.sei.transformation.editor.model.ModelType;
import edu.pku.sei.transformation.editor.model.Rule;
import edu.pku.sei.transformation.editor.model.Transformation;
import edu.pku.sei.transformation.editor.model.TypedModel;
import edu.pku.sei.transformation.editor.model.execution.TransformationExecution;

public class ATLModuleAdapter implements IATLModule {
	public TransformationExecution transExe = null;
	AtomicTransformation transformation = null;
	List<IATLRule> rules = null;

	public ATLModuleAdapter(TransformationExecution execution) throws Exception {
		this.transExe = execution;
		if (transExe.getTransformation() instanceof AtomicTransformation) {
			transformation = (AtomicTransformation) transExe
					.getTransformation();
		} else {
			throw new Exception("only atomic transformation can generate code");
		}
	}

	@Override
	public IATLHeader getHeader() {
		return new ATLHeaderAdapter(transExe);
	}

	@Override
	public List<IATLHelper> getHelpers() {
		return new ArrayList<IATLHelper>();
	}

	@Override
	public List<IATLImport> getImports() {
		return new ArrayList<IATLImport>();
	}

	@Override
	public List<IATLRule> getRules() {
		if (rules == null) {
			rules = new ArrayList<IATLRule>();
			for (Object obj : transformation.getRules()) {
				if (obj instanceof Rule) {
					Rule r = (Rule) obj;
					IATLRule atlRule;
					try {
						atlRule = new ATLRuleAdapter(r, transExe.getDirection());
						rules.add(atlRule);
					} catch (Exception e) {
						e.printStackTrace();
						System.out.println("rule:" + r.getName()
								+ " convert failed");
					}
				}
			}
		}
		return rules;
	}

	@Override
	public List<IATLMetaModel> getMetaModels() {
		ArrayList<IATLMetaModel> metamodels = new ArrayList<IATLMetaModel>();
		HashSet<MetaModel> set = new HashSet<MetaModel>();
		Transformation transformation = transExe.getTransformation();
		for (TypedModel obj : transformation.getTypedModel()) {
			Object metamodel = obj.getType();
			if (metamodel instanceof ModelType)
				set.add((MetaModel) ((ModelType) metamodel).getType());
		}
		for (MetaModel metaModel : set) {
			metamodels.add(new ATLMetaModelAdapter(metaModel));
		}
		return metamodels;
	}
}
